#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/gpio.h>

#include "btn_desc.h"

struct input_dev *btn_input=NULL;
struct timer_list btn_timer;


irqreturn_t btn_isr(int irqnum,void *dev){
    btn_timer.data=(unsigned long)dev;
    mod_timer(&btn_timer,jiffies+msecs_to_jiffies(10));

    return IRQ_HANDLED;
}

void btn_timer_func(unsigned long data){
    int status=0;
    btn_desc_t *pdata=(btn_desc_t *)data;
    status=gpio_get_value(pdata->gpio);

    input_event(btn_input,EV_KEY,
                pdata->code,!status);
    input_event(btn_input,EV_SYN,0,0);
}

int btn_probe(struct platform_device *pdev){
    int i=0;
    int ret=0;
    struct resource *res=NULL;
    btn_desc_t *pdata=pdev->dev.platform_data;
    int key_nums=pdev->num_resources;

    btn_input=input_allocate_device();
    btn_input->name="mybuttons";
    set_bit(EV_KEY,btn_input->evbit);
    set_bit(EV_SYN,btn_input->evbit);
    set_bit(EV_REP,btn_input->evbit);

    for(i=0;i<key_nums;i++){
        set_bit(pdata[i].code,btn_input->keybit);
    }
    ret=input_register_device(btn_input);
    for(i=0;i<key_nums;i++){
        res=platform_get_resource(pdev,IORESOURCE_IRQ,i);
        ret=request_irq(res->start,btn_isr,
                IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
                pdata[i].name,
               &pdata[i]);
    }
    init_timer(&btn_timer);
    btn_timer.function=btn_timer_func;
    return 0;
}
int btn_remove(struct platform_device *pdev){
    int i=0;
    struct resource *res=NULL;
    btn_desc_t *pdata=pdev->dev.platform_data;
    int key_nums=pdev->num_resources;
    del_timer(&btn_timer);
    for(;i<key_nums;i++){
        res=platform_get_resource(pdev,IORESOURCE_IRQ,i);
        free_irq(res->start,pdata);
    }
    input_unregister_device(btn_input);
    input_free_device(btn_input);
    return 0;
}

static struct platform_driver btn_drv = {
    .driver = {
        .name = "mybuttons",
    },
    .probe = btn_probe,
    .remove = btn_remove,
};

static int __init btn_drv_init(void){
    platform_driver_register(&btn_drv);
    return 0;
}
static void __exit btn_drv_exit(void){
    platform_driver_unregister(&btn_drv);
}
module_init(btn_drv_init);
module_exit(btn_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGY");

